package com.baiku.sanhos.controller;

import com.alibaba.fastjson.JSON;
import com.baiku.sanhos.domain.LoginUser;
import com.baiku.sanhos.domain.SmsCodeAuthenticationToken;
import com.baiku.sanhos.mapper.AdminMapper;
import com.baiku.sanhos.mapper.DoctorMapper;
import com.baiku.sanhos.mapper.UserMapper;
import com.baiku.sanhos.pojo.dto.UserLoginDTO;
import com.baiku.sanhos.pojo.dto.UserSendLoginDTO;
import com.baiku.sanhos.pojo.po.UserLoginInfoPO;
import com.baiku.sanhos.pojo.vo.AdminVo;
import com.baiku.sanhos.pojo.vo.DoctorVo;
import com.baiku.sanhos.pojo.vo.UserVo;
import com.baiku.sanhos.provider.SmsAuthenticationProvider;
import com.baiku.sanhos.provider.UsernamePassAuthenticationProvider;
import com.baiku.sanhos.response.ResultVO;
import com.baiku.sanhos.utils.BaseResult;
import com.baiku.sanhos.utils.JWTEasyUtil;
import com.baiku.sanhos.utils.RedisCache;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 准备加入IP验证
 */
@RestController
@RequestMapping("/pa/users")
@Api(tags = "登录管理")
@Slf4j
public class LoginController {

    @Autowired
    private JWTEasyUtil jwtEasyUtil;
    @Autowired
    private SmsAuthenticationProvider smsCodeAuthenticationProvider;
    @Autowired
    RedisCache redisCache;
    @Autowired
    UsernamePassAuthenticationProvider usernamePassAuthenticationProvider;
    @Autowired
    private DoctorMapper doctorMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AdminMapper adminMapper;
    private static final String REDIS_LONGIN_TOKEN = "login:token:";





    @PostMapping("/login")
    public ResultVO login(@RequestBody UserLoginDTO userLoginDTO,
                          @ApiIgnore HttpServletRequest request){

        //AuthenticationManager authenticate进行用户认证(模拟将信息封装到authenticationToken这个对象里面)
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userLoginDTO.getUsername(),userLoginDTO.getPassword());
        /*进行认证，同时会调用数据库来验证帐号密码*/
        Authentication authenticate = usernamePassAuthenticationProvider.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            return ResultVO.fail();
        }
        //如果认证通过了，使用userid生成一个jwt
        //加入username的原因，我们的user、doctor和Admin三个表是分开的！
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();

        String username = loginUser.getUser().getUsername();
        String userid = loginUser.getUser().getId().toString();
        Map<String,Object> claim = new HashMap<>();


        claim.put("userId",userid);

        redisCache.setCacheObject("login:"+userid,loginUser);


        String jwt = jwtEasyUtil.createToken(userid);

        redisCache.setCacheObject(REDIS_LONGIN_TOKEN+userid,jwt, 86400,TimeUnit.MINUTES);

        Map<String,String> map = new HashMap<>();
        map.put("token",jwt);
        if(userLoginDTO.getFlag()==2){
            //用户
            UserVo userVo = userMapper.selectByUserName(username);
            map.put("userId", String.valueOf(userVo.getId()));
            map.put("username", userVo.getUsername());
            map.put("Avatar", userVo.getAvatar());
            map.put("nickName",userVo.getNickname());

        } else if (userLoginDTO.getFlag()==1) {
            //医生
            DoctorVo doctorVo = doctorMapper.selectByUserName(username);
            map.put("userId", String.valueOf(doctorVo.getId()));
            map.put("username", doctorVo.getUsername());
            map.put("no", doctorVo.getNo());
            map.put("Avatar", doctorVo.getAvatar());
        }else {
            //管理员
            AdminVo adminVo = adminMapper.selectByUserName(username);
            map.put("userId", String.valueOf(adminVo.getId()));
            map.put("username", adminVo.getUsername());
            map.put("Avatar", adminVo.getAvatar());

        }
        //把完整的用户信息存入redis
        /*从发送请求出获得IP和设备信息*/
        String remoteAddr=request.getRemoteAddr();
        String userAgent=request.getHeader("User-Agent");


        Collection<? extends GrantedAuthority> authorities = loginUser.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        UserLoginInfoPO userLoginInfoPO=new UserLoginInfoPO();
        userLoginInfoPO.setUserAgent(userAgent);
        userLoginInfoPO.setIp(remoteAddr);
        userLoginInfoPO.setAuthoritiesJsonString(authoritiesJsonString);
        redisCache.saveLoginInfo(jwt,userLoginInfoPO);

        return new ResultVO(1001,"登录成功",map);
    }

    //登出操作
    @PostMapping("/logout")
    @ApiOperation("用户退出登录")

    public ResultVO logout() {

        log.debug("开始处理【用户退出登录】的请求，无参数");
        SecurityContextHolder.clearContext();



        return new ResultVO(2009,"登出成功");
    }


    @PostMapping("/msLogin")///pa/users/login
    public ResultVO msLogin(@RequestBody UserSendLoginDTO userSendLoginDTO,
                            @ApiIgnore HttpServletRequest request){
        //给电话号码加尾号flag，后面再用截取的方式获得尾号
        String phone = userSendLoginDTO.getPhone()+userSendLoginDTO.getFlag();


        //AuthenticationManager authenticate进行用户认证(模拟将信息封装到authenticationToken这个对象里面)
        SmsCodeAuthenticationToken authenticationToken = new SmsCodeAuthenticationToken(phone,userSendLoginDTO.getCode());
        /*进行认证，同时会调用数据库来验证*/
        Authentication authenticate = smsCodeAuthenticationProvider.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            return ResultVO.fail();
        }
        //如果认证通过了，使用username生成一个jwt  username帐号唯一
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();

        String username = loginUser.getUser().getUsername();
        String userid = loginUser.getUser().getId().toString();
        Map<String,Object> claim = new HashMap<>();


        claim.put("userId",userid);

        redisCache.setCacheObject("login:"+userid,loginUser);


        String jwt = jwtEasyUtil.createToken(userid);
        redisCache.setCacheObject(REDIS_LONGIN_TOKEN+userid,jwt, 86400,TimeUnit.MINUTES);
        Map<String,String> map = new HashMap<>();

        map.put("token",jwt);

        if(userSendLoginDTO.getFlag()==2){
            //用户
            UserVo userVo = userMapper.selectByUserName(username);
            map.put("userId", String.valueOf(userVo.getId()));
            map.put("username", userVo.getUsername());
            map.put("Avatar", userVo.getAvatar());
            map.put("nickName",userVo.getNickname());


        } else if (userSendLoginDTO.getFlag()==1) {
            //医生
            DoctorVo doctorVo = doctorMapper.selectByUserName(username);
            map.put("userId", String.valueOf(doctorVo.getId()));
            map.put("username", doctorVo.getUsername());
            map.put("no", doctorVo.getNo());
            map.put("Avatar", doctorVo.getAvatar());
        }else {
            //管理员
            AdminVo adminVo = adminMapper.selectByUserName(username);
            map.put("userId", String.valueOf(adminVo.getId()));
            map.put("username", adminVo.getUsername());
            map.put("Avatar", adminVo.getAvatar());



        }
        //把完整的用户信息存入redis  userid作为key
        /*从发送请求出获得IP和设备信息*/
        String remoteAddr=request.getRemoteAddr();
        String userAgent=request.getHeader("User-Agent");


        Collection<? extends GrantedAuthority> authorities = loginUser.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        UserLoginInfoPO userLoginInfoPO=new UserLoginInfoPO();
        userLoginInfoPO.setUserAgent(userAgent);
        userLoginInfoPO.setIp(remoteAddr);
        userLoginInfoPO.setAuthoritiesJsonString(authoritiesJsonString);
        redisCache.saveLoginInfo(jwt,userLoginInfoPO);




        return new ResultVO(1001,"登录成功",map);
    }



}
